<script setup>
import GBK from 'gbk.js';
import { nanoid } from 'nanoid'
import { getBookSources, request, ruleAnalysis, getBookSourceRule, getBookDetails } from '../services/bookService'
import { setStore, getStore } from '../services/book-store'
import { ref, getCurrentInstance, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';

const { proxy } = getCurrentInstance();
const bookshelf = ref(getStore('bookshelf') || []);
const bookSources = getBookSources();
const router = useRouter();
const keyword = ref('');
const searchResults = ref([]);
const loading = ref(false);
const showBackToTop = ref(false);

// 控制返回顶部按钮显示
const handleScroll = () => {
  showBackToTop.value = window.scrollY > 300;
};

// 返回顶部
const scrollToTop = () => {
  window.scrollTo({
    top: 0,
    behavior: 'smooth'
  });
};

onMounted(() => {
  window.addEventListener('scroll', handleScroll);
});

onUnmounted(() => {
  window.removeEventListener('scroll', handleScroll);
});


// 处理搜索结果数据映射
const mapSearchResult = (result, sourceName, bookSourceUrl) => {
  return {
    title: result.name || '',
    author: result.author || '',
    cover: result.coverUrl || '',
    intro: result.intro || '暂无简介',
    category: result.kind || '',
    lastChapter: result.lastChapter || '',
    sourceName: sourceName,
    source: bookSourceUrl,
    url: result.bookUrl || ''
  };
};

// 详情页面数据映射
const mapDetailResult = (result) => {
  return {
    title: result.name || '',
    author: result.author || '',
    cover: result.coverUrl || '',
    intro: result.intro || '暂无简介',
    category: result.kind || '',
    lastChapter: result.lastChapter || '',
    tocUrl: result.tocUrl || ''
  };
}

const ruleGetBookList = (doc, ruleObj, url) => {
  let bookListEl = ruleAnalysis(ruleObj.bookList, doc, url);
  
  let info = bookListEl.map(item=>{
    let obj = {};
    for(let key in ruleObj){
      if(key === 'bookList')continue;
      if(!ruleObj[key]){
        obj[key] = '';
        continue;
      };
      let value = ruleAnalysis(ruleObj[key], item, url);
      obj[key] = value;
    }
    
    return obj
  }) 
  return info.sort((a, b) => {
    if (a.name === keyword.value) return -1;
    if (a.name.includes(keyword.value)) return 1;
    return 0;
  });
};


// params 处理
const searchParamsHandle = async (bookSource, key) => {
  let params = {}
  bookSource.searchUrl?.params && Object.keys(bookSource.searchUrl.params).forEach(item => {
    if(bookSource.searchUrl.params[item] === 'key'){
      if(/gbk/i.test(bookSource.searchUrl?.code)){
        params[item] = GBK.URI.encodeURIComponent(key);
      }else{
        params[item] = key
      }
    }else{
      params[item] = bookSource.searchUrl.params[item]
    }
  })
  let url;
  if(/get/i.test(bookSource.searchUrl.method)){
    url = bookSource.searchUrl.url.replace(/{{key}}/, key)
    if(bookSource.searchUrl?.params){
      url = bookSource.searchUrl.url + '?' + new URLSearchParams(params).toString().replace(/%25/g, '%');
    }
  }
  if(/post/i.test(bookSource.searchUrl.method)){
    url = bookSource.searchUrl.url;
  }

  let res = await request(url, {
    headers: bookSource.header,
    method: bookSource.searchUrl.method,
    body: bookSource.searchUrl.method === 'POST' ? new URLSearchParams(params).toString().replace(/%25/g, '%') : null
  })

  let parser = new DOMParser();
  let doc = parser.parseFromString(res.html, 'text/html');

  let info = ruleGetBookList(doc, bookSource.ruleSearch, res.url);

  // 使用mapSearchResult处理结果
  const mappedResults = info.map(item => mapSearchResult(item, bookSource.bookSourceName, bookSource.bookSourceUrl));
  
  if(keyword.value !== key)return mappedResults;

  searchResults.value = [...searchResults.value, ...mappedResults].sort((a, b) => {
    if (a.title === keyword.value) return -1;
    if (a.title.includes(keyword.value)) return 1;
    return 0;
  })
  
  return mappedResults
}

// 搜索函数
const search = async () => {
  let key = keyword.value;
  if (!keyword.value.trim()) return;
  loading.value = true;
  searchResults.value = [];
  await Promise.allSettled(bookSources.map((item) =>  searchParamsHandle(item, key)))
  if(keyword.value!== key)return;
  loading.value = false;
  console.log(searchResults.value);
};


const isInShelf = (book) => {
  return bookshelf.value.some(item => item.url === book.url)
}

const addToShelf = async (book) => {
  if(book.loading)return;
  book.loading = true;
  let _id = nanoid()
  let bookSourceRule = getBookSourceRule(book);
  try {
    let detail = await getBookDetails(book, bookSourceRule);
    delete book.loading;
    book = {
      ...book,
      ...mapDetailResult(detail.info),
    }
    let shelf = getStore('bookshelf') || [];

    bookshelf.value = [{
        ...book,
        bookType: 1,
        _id
      },
      ...shelf
    ]
    setStore('bookshelf', bookshelf.value)
  } catch (error) {
    proxy.$toast.error('资源加载错误，无法加入书架');
  }
 

};
</script>

<template>
  <div class="search-container">
    <div class="search-bar">
      <input type="text" v-model="keyword" placeholder="请输入书名或作者" @keyup.enter="search">
      <button @click="search" :disabled="loading">
        <span v-if="!loading">搜索</span>
        <span v-else class="loading-indicator"></span>
      </button>
    </div>

    <div v-if="bookSources.length && !keyword && !searchResults.length" class="search-tips">
      <p>输入书名或作者名开始搜索</p>
      <!-- <p>当前为多个书源搜索</p> -->
    </div>

    <div v-else-if="bookSources.length && loading && !searchResults.length" class="loading">
      <span class="loading-indicator"></span>
      正在搜索中...
    </div>

    <div v-else-if="bookSources.length && searchResults.length === 0" class="empty-result">
      未找到相关书籍
    </div>

    <div v-else-if="!bookSources.length" class="no-source">当前没有书源，<span @click="$router.replace('/source-manager')">去添加书源</span></div>

    <div v-else class="search-results">
      <div v-for="(book, index) in searchResults" :key="index" class="result-item">
        <img v-if="book.cover" :src="book.cover" :alt="book.title" class="book-cover">
        <img v-else class="book-cover" src="../assets/book.svg" alt="">
        <div class="book-info-container">
          <div class="book-header">
            <div class="book-title">{{ book.title }}</div>
            <div class="book-meta">
              <span class="author"><span class="icon-user"></span>{{ book.author }}</span>
              <span v-if="book.category" class="category">{{ book.category }}</span>
              <span class="source">{{ book.sourceName }}</span>
            </div>
          </div>
          <div class="book-intro">{{ book.intro }}</div>
          <div class="book-footer">
            <div class="book-last-chapter" :title="book.lastChapter">
              <span class="icon-book"></span>{{ book.lastChapter }}
            </div>
            <div class="book-actions">
              <!-- <button class="action-button read-button" @click="viewBook(book)">开始阅读</button> -->
              <button v-if="!isInShelf(book)" :disabled="book.loading" class="action-button shelf-button read-button" @click="addToShelf(book)">加入书架</button>
              <button disabled v-else class="action-button shelf-button">已加入书架</button>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 返回顶部按钮 -->
    <div v-show="showBackToTop" class="back-to-top" @click="scrollToTop">
      <span class="arrow-up">↑</span>
    </div>
  </div>
</template>

<style scoped>
.search-container {
  padding: 16px;
  max-width: 1200px;
  margin: 0 auto;
}

.search-bar {
  display: flex;
  margin-bottom: 20px;
}

.search-bar input {
  flex: 1;
  padding: 6px 18px;
  border: 1px solid #ddd;
  border-radius: 8px 0 0 8px;
  font-size: 14px;
  height: 30px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
  background-color: #fff;
  color: #333;
}

@media (prefers-color-scheme: dark) {
  .search-bar input {
    background-color: #2c3e50;
    color: #ecf0f1;
    border-color: #34495e;
  }
}

.search-bar input:focus {
  outline: none;
  border-color: var(--blue, #4a90e2);
  box-shadow: 0 2px 12px rgba(74, 144, 226, 0.15);
}

.search-bar button {
  /* padding: 12px 24px; */
  border: none;
  border-radius: 0 8px 8px 0;
  background-color: var(--blue, #4a90e2);
  color: white;
  font-size: 14px;
  height: 44px;
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 80px;
}

.search-bar button:hover {
  background-color: var(--blue-dark, #357abd);
}

.search-bar button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.search-bar .loading-indicator {
  margin: 0;
  width: 16px;
  height: 16px;
}

.search-results {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.result-item {
  display: flex;
  padding: 16px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

@media (prefers-color-scheme: dark) {
  .result-item {
    background: #2c3e50;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  }
}

.result-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.book-cover {
  width: 120px;
  height: 160px;
  object-fit: cover;
  border-radius: 4px;
  margin-right: 20px;
}

.book-info-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.book-header {
  margin-bottom: 12px;
}

.book-title {
  font-size: 18px;
  font-weight: bold;
  color: #333;
  margin-bottom: 8px;
}

@media (prefers-color-scheme: dark) {
  .book-title {
    color: #ecf0f1;
  }
}

.book-meta {
  display: flex;
  gap: 16px;
  color: #666;
  font-size: 14px;
}

@media (prefers-color-scheme: dark) {
  .book-meta {
    color: #b2bec3;
  }
}

.book-meta .author,
.book-meta .category {
  display: flex;
  align-items: center;
  gap: 4px;
}

.book-intro {
  color: #666;
  font-size: 14px;
  line-height: 1.5;
  margin: 12px 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (prefers-color-scheme: dark) {
  .book-intro {
    color: #b2bec3;
  }
}

.book-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto;
}

.book-last-chapter {
  color: #666;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 50%;
}

@media (prefers-color-scheme: dark) {
  .book-last-chapter {
    color: #b2bec3;
  }
}

.book-actions {
  display: flex;
  gap: 12px;
}

.action-button {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.action-button.read-button {
  background-color: var(--blue, #4a90e2);
  color: white;
}

.action-button.read-button:hover {
  background-color: var(--blue-dark, #357abd);
}

.shelf-button {
  background-color: #f5f5f5;
  color: #666;
}

@media (prefers-color-scheme: dark) {
  .shelf-button {
    background-color: #34495e;
    color: #ecf0f1;
  }
}

.shelf-button:hover {
  background-color: #e8e8e8;
}

@media (prefers-color-scheme: dark) {
  .shelf-button:hover {
    background-color: #2c3e50;
  }
}

.search-tips,
.loading,
.empty-result,
.no-source {
  text-align: center;
  padding: 40px 0;
  color: #666;
  line-height: 20px;
}

@media (prefers-color-scheme: dark) {
  .search-tips,
  .loading,
  .empty-result,
  .no-source {
    color: #b2bec3;
  }
}

.no-source span{
  color: var(--blue, #4a90e2);
  cursor: pointer;
}

.loading{
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-indicator {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2px solid #f3f3f3;
  border-top: 2px solid var(--blue, #4a90e2);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@media (prefers-color-scheme: dark) {
  .loading-indicator {
    border: 2px solid #34495e;
    border-top: 2px solid var(--blue, #4a90e2);
  }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@media (max-width: 768px) {
  .result-item {
    flex-direction: column;
  }

  .book-cover {
    width: 100%;
    height: 200px;
    margin-right: 0;
    margin-bottom: 16px;
  }

  .book-footer {
    flex-direction: column;
    gap: 12px;
  }

  .book-last-chapter {
    max-width: 100%;
  }

  .book-actions {
    width: 100%;
  }

  .action-button {
    flex: 1;
  }
}
.book-meta .source {
  background-color: #f0f0f0;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
  color: #666;
  margin-left: 8px;
}

@media (prefers-color-scheme: dark) {
  .book-meta .source {
    background-color: #34495e;
    color: #ecf0f1;
  }
}

.back-to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: var(--blue, #4a90e2);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  transition: all 0.3s;
  z-index: 900;
}

.back-to-top:hover {
  transform: scale(1.1);
  background-color: var(--blue-dark, #357abd);
}

.arrow-up {
  font-size: 20px;
  font-weight: bold;
}
</style>